﻿namespace HZY.Framework.Repository.EntityFramework.Attributes;

/// <summary>
/// 表 id
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class TableIdAttribute : Attribute
{
    /// <summary>
    /// id 类型
    /// </summary>
    public IdType IdType { get; set; } = IdType.SnowflakeId;

    /// <summary>
    /// 表 id
    /// </summary>
    public TableIdAttribute()
    {
    }

    /// <summary>
    /// 表 id
    /// </summary>
    /// <param name="idType"></param>
    public TableIdAttribute(IdType idType)
    {
        IdType = idType;
    }

    /// <summary>
    /// 根据字段填充类型获取字段
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static TableIdAttribute? GetTableIdAttribute(PropertyInfo propertyInfo)
    {
        return propertyInfo.GetCustomAttribute<TableIdAttribute>();
    }

    /// <summary>
    /// 处理id逻辑
    /// </summary>
    /// <param name="entityEntry"></param>
    /// <param name="propertyEntry"></param>
    /// <param name="entityState"></param>
    /// <param name="snowflakeId"></param>
    public virtual void Handle(EntityEntry entityEntry, PropertyEntry propertyEntry, EntityState entityState,
        long snowflakeId)
    {
        if (EntityFrameworkUtil.IsNullableType(propertyEntry.Metadata.ClrType) && propertyEntry.CurrentValue != null)
        {
            return;
        }

        var propertyInfo = propertyEntry.Metadata.PropertyInfo;
        var propertyType = propertyInfo?.PropertyType;

        if (IdType == IdType.SnowflakeId)
        {
            long.TryParse(propertyEntry.CurrentValue?.ToString(), out var result);
            if (result > 0)
            {
                return;
            }

            if (snowflakeId < 1)
            {
                var idGenerator = entityEntry.Context.GetService<IdGenerator>();
                snowflakeId = idGenerator.CreateId();
            }

            // 判断  propertyEntry.CurrentValue 是否为 long 类型
            if (propertyType == typeof(long) || propertyType == typeof(long?))
            {
                propertyEntry.CurrentValue = snowflakeId;
            }

            if (propertyType == typeof(string))
            {
                propertyEntry.CurrentValue = snowflakeId.ToString();
            }

            return;
        }

        // uuid / guid
        if (IdType == IdType.UuId)
        {
            if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
            {
                Guid.TryParse(propertyEntry.CurrentValue?.ToString(), out var guid);
                if (guid != Guid.Empty)
                {
                    return;
                }
            }

            propertyEntry.CurrentValue = Guid.NewGuid();
        }

        // uuid string
        if (IdType == IdType.UuIdString)
        {
            propertyEntry.CurrentValue = Guid.NewGuid().ToString("N");
        }
    }

    /// <summary>
    /// 处理id逻辑
    /// </summary>
    /// <param name="auditInfo"></param>
    /// <param name="snowflakeId"></param>
    /// <param name="serviceProvider"></param>
    public virtual void HandleByFreeSql(AuditValueEventArgs auditInfo, long snowflakeId,
        IServiceProvider? serviceProvider)
    {
        var propertyInfo = auditInfo.Property;
        var propertyType = propertyInfo?.PropertyType;

        if (IdType == IdType.SnowflakeId)
        {
            long.TryParse(auditInfo.Value?.ToString(), out var result);
            if (result > 0)
            {
                return;
            }

            if (snowflakeId < 1)
            {
                var idGenerator = serviceProvider?.GetService<IdGenerator>();
                snowflakeId = idGenerator?.CreateId() ?? 0;
            }

            // 判断  propertyEntry.CurrentValue 是否为 long 类型
            if (propertyType == typeof(long) || propertyType == typeof(long?))
            {
                auditInfo.Value = snowflakeId;
            }

            if (propertyType == typeof(string))
            {
                auditInfo.Value = snowflakeId.ToString();
            }

            return;
        }

        // uuid / guid
        if (IdType == IdType.UuId)
        {
            if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
            {
                Guid.TryParse(auditInfo.Value?.ToString(), out var guid);
                if (guid != Guid.Empty)
                {
                    return;
                }
            }

            auditInfo.Value = Guid.NewGuid();
        }

        // uuid string
        if (IdType == IdType.UuIdString)
        {
            auditInfo.Value = Guid.NewGuid().ToString("N");
        }
    }

    /// <summary>
    /// 处理id逻辑
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="serviceProvider"></param>
    public static void HandleByEntity<T>(T entity, IServiceProvider? serviceProvider)
    {
        if (entity is null)
        {
            return;
        }

        var type = entity.GetType();
        var propertyInfos = type.GetProperties();
        foreach (var item in propertyInfos)
        {
            var tableIdAttribute = TableIdAttribute.GetTableIdAttribute(item);
            if (tableIdAttribute is null)
            {
                continue;
            }

            var value = item.GetValue(entity);

            var propertyInfo = item;
            var propertyType = propertyInfo.PropertyType;

            if (tableIdAttribute.IdType == IdType.SnowflakeId)
            {
                long.TryParse(value?.ToString(), out var result);
                if (result > 0)
                {
                    return;
                }

                var idGenerator = serviceProvider?.GetService<IdGenerator>();
                var snowflakeId = idGenerator?.CreateId() ?? 0;

                // 判断  propertyEntry.CurrentValue 是否为 long 类型
                if (propertyType == typeof(long) || propertyType == typeof(long?))
                {
                    item.SetValue(entity, snowflakeId);
                }

                if (propertyType == typeof(string))
                {
                    item.SetValue(entity, snowflakeId.ToString());
                }

                return;
            }

            // uuid / guid
            if (tableIdAttribute.IdType == IdType.UuId)
            {
                if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
                {
                    Guid.TryParse(value?.ToString(), out var guid);
                    if (guid != Guid.Empty)
                    {
                        return;
                    }
                }

                item.SetValue(entity, Guid.NewGuid());
            }

            // uuid string
            if (tableIdAttribute.IdType == IdType.UuIdString)
            {
                item.SetValue(entity, Guid.NewGuid().ToString("N"));
            }
        }
    }
}

/// <summary>
/// id 类型
/// </summary>
public enum IdType
{
    /// <summary>
    /// 雪花id
    /// </summary>
    SnowflakeId = 0,

    /// <summary>
    /// uuid
    /// </summary>
    UuId = 1,

    /// <summary>
    /// uuid 字符串
    /// </summary>
    UuIdString = 2
}